home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
UTILITY1
/
MSWSRC35.ZIP
/
MATH.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-10
|
15KB
|
718 lines
/*
* math.c logo math functions module dvb
*
* Copyright (C) 1989 The Regents of the University of California
* This Software may be copied and distributed for educational,
* research, and not for profit purposes provided that this
* copyright and statement are included in all such copies.
*
*/
#include "logo.h"
#include "globals.h"
#include <signal.h>
#include <setjmp.h>
#include <math.h>
#define isdigit(dig) (dig >= '0' && dig <= '9')
int numberp(NODE *snd)
{
int dl,dr, pcnt, plen;
char *p;
if (is_number(snd)) return(1);
snd = cnv_node_to_strnode(snd);
if (snd == UNBOUND) return(0);
p = getstrptr(snd); plen = getstrlen(snd); pcnt = dl = dr = 0;
if (plen >= MAX_NUMBER) {
return(0);
}
if (pcnt < plen && *p == '-')
p++, pcnt++;
while (pcnt < plen && isdigit(*p))
p++, pcnt++, dl++;
if (pcnt < plen && *p == '.') {
p++, pcnt++;
while (pcnt < plen && isdigit(*p))
p++, pcnt++, dr++;
}
if (pcnt < plen && (dl || dr) && (*p == 'E' || *p == 'e')) {
p++, pcnt++;
if (pcnt < plen && *p == '+' || *p == '-')
p++, pcnt++;
while (pcnt < plen && isdigit(*p))
p++, pcnt++, dr++;
}
if ((dl == 0 && dr == 0) || pcnt != plen)
return (0);
else
return (dr + 1);
}
NODE *lrandom(NODE *arg)
{
NODE *val;
long r;
val = pos_int_arg(arg);
if (NOT_THROWING) {
#ifdef bsd
r = (getint(val) == 0 ? 0 : random() % getint(val));
#else
r = (getint(val) == 0 ? 0 : rand() % getint(val));
#endif
val = newnode(INT);
setint(val, (FIXNUM)r);
return(val);
} else return(UNBOUND);
}
NODE *lrerandom(NODE *arg)
{
int seed=1;
if (arg != NIL) {
seed = int_arg(arg);
}
if (NOT_THROWING) {
#ifdef bsd
srandom((int)seed);
#else
srand((int)seed);
#endif
}
return(UNBOUND);
}
jmp_buf oflo_buf;
#ifdef __ZTC__
#define sig_arg 0
void handle_oflo(int sig) {
#else
#define sig_arg 0
void handle_oflo(int sig) {
#endif
longjmp(oflo_buf,1);
}
#ifdef vax
void allow_intov() {
long dummy;
register long *p = &dummy;
p[2] |= 040; /* Turn on IV enable in saved PSW (I hate the vax) */
}
double infnan() {
longjmp(oflo_buf,1);
}
#endif
#ifdef sun
int matherr(struct exception *x)
{
if (x->type == UNDERFLOW) return(1);
longjmp(oflo_buf,1);
}
#endif
#ifdef mac
FLONUM degrad = 0.017453292520;
#else
FLONUM degrad = 3.141592653589793227020265931059839203954/180.0;
#endif
NODE *binary(NODE *args, char fcn)
{
NODE *arg, *val;
BOOLEAN imode;
FIXNUM iarg, ival, oval, nval;
FLONUM farg, fval;
int sign, wantint=0;
arg = numeric_arg(args);
args = cdr(args);
if (stopping_flag == THROWING) return UNBOUND;
if (nodetype(arg) == INT) {
imode = TRUE;
ival = getint(arg);
} else {
imode = FALSE;
fval = getfloat(arg);
}
if (args == NIL) { /* one argument supplied */
if (imode)
switch(fcn) {
case '-': ival = -ival; break;
case '~': ival = ~ival; break;
case 's':
case 'c':
case 't':
case 'S':
case 'C':
case 'T':
case 'q':
case 'e':
case 'g':
case 'n':
case '/':
imode = FALSE;
fval = (FLONUM)ival;
break;
}
if (imode == FALSE) {
if (!setjmp(oflo_buf)) {
switch(fcn) {
case '-': fval = -fval; break;
case '/':
if (fval == 0.0)
err_logo(BAD_DATA_UNREC,arg);
else
fval = 1/fval;
break;
case '~': err_logo(BAD_DATA_UNREC,arg); break;
case 'c':
fval = 90.0 - fval;
case 's':
/* Kahan sez we can't just multiply any old
* angle by degrad, but have to get into the
* range 0-45 first */
sign = (fval < 0.0);
if (sign) fval = -fval;
#ifndef unix
fval = fmod(fval,360.0);
#else
fval = drem(fval,360.0);
#endif
if (fval > 180.0) {
fval -= 180.0;
sign = !sign;
}
if (fval > 90.0) fval = 180.0 - fval;
if (fval > 45.0)
fval = cos((90.0-fval)*degrad);
else
fval = sin(fval*degrad);
if (sign) fval = -fval;
break;
case 't': fval = atan(fval)/degrad; break;
case 'S': fval = sin(fval); break;
case 'C': fval = cos(fval); break;
// case 's': fval = sin(fval*degrad); break;
// case 'c': fval = cos(fval*degrad); break;
case 'T': fval = atan(fval); break;
case 'q': fval = sqrt(fval); break;
case 'e': fval = exp(fval); break;
case 'g': fval = log10(fval); break;
case 'n': fval = log(fval); break;
case 'r':
fval += (fval < 0 ? -0.5 : 0.5);
case 'i':
#ifdef vax
allow_intov();
#else
if (fval > (FLONUM)MAXINT ||
fval < -(FLONUM)MAXINT)
handle_oflo(sig_arg);
#endif
signal(SIGFPE, handle_oflo);
ival = (FIXNUM)fval;
imode = TRUE;
signal(SIGFPE, SIG_DFL);
break;
}
} else { /* overflow */
if (fcn == 'r' || fcn == 'i') {
if (fval < 0.0)
fval = ceil(fval);
else
fval = floor(fval);
} else
err_logo(BAD_DATA_UNREC,arg);
}
} /* end float case */
} /* end monadic */
while (args != NIL && NOT_THROWING) {
arg = numeric_arg(args);
args = cdr(args);
if (stopping_flag == THROWING) return UNBOUND;
if (nodetype(arg) == INT) {
if (imode) iarg = getint(arg);
else farg = (FLONUM)getint(arg);
} else {
if (imode) {
fval = (FLONUM)ival;
imode = FALSE;
}
farg = getfloat(arg);
}
if (imode) {
oval = ival;
#ifdef vax
allow_intov();
#endif
signal(SIGFPE, handle_oflo);
if (setjmp(oflo_buf) == 0) {
switch(fcn) {
#ifdef vax
case '+': ival += iarg; break;
case '-': ival -= iarg; break;
case '*': ival *= iarg; break;
#else
case '-': iarg = -iarg;
case '+':
if (iarg < 0) {
nval = ival + iarg;
if (nval >= ival)
handle_oflo(sig_arg);
else ival = nval;
} else {
nval = ival + iarg;
if (nval < ival)
handle_oflo(sig_arg);
else ival = nval;
}
break;
#endif
case '/':
if (iarg == 0)
err_logo(BAD_DATA_UNREC,arg);
else
if (ival % iarg != 0) {
imode = FALSE;
fval = (FLONUM)ival;
farg = (FLONUM)iarg;
}
else ival /= iarg;
break;
case '%':
ival %= iarg;
if ((ival < 0) != (iarg < 0))
ival += iarg;
break;
case '&': ival &= iarg; break;
case '|': ival |= iarg; break;
case '^': ival ^= iarg; break;
case 'a':
case 'l':
if (iarg < 0) {
if (fcn == 'a')
ival >>= -iarg;
else
ival = (unsigned)ival
>> -iarg;
} else
ival <<= iarg;
break;
#ifndef vax
case '*':
if (ival < SAFEINT && ival > -SAFEINT &&
iarg < SAFEINT && iarg > -SAFEINT) {
ival *= iarg;
break;
}
wantint++;
#endif
default: /* math library */
imode = FALSE;
fval = (FLONUM)ival;
farg = (FLONUM)iarg;
}
} else { /* integer overflow detected */
imode = FALSE;
fval = (FLONUM)oval;
farg = (FLONUM)iarg;
}
signal(SIGFPE,SIG_DFL);
}
if (imode == FALSE) {
signal(SIGFPE,handle_oflo);
if (setjmp(oflo_buf) == 0) {
switch(fcn) {
case '+': fval += farg; break;
case '-': fval -= farg; break;
case '*':
fval *= farg;
#ifndef vax
if (wantint) {
wantint = 0;
if (fval <= MAXINT && fval >= -MAXINT) {
imode = TRUE;
ival = fval;
}
}
#endif
break;
case '/': if (farg == 0.0)
err_logo(BAD_DATA_UNREC,arg);
else
fval /= farg;
break;
case 't':
fval = atan2(farg,fval)/degrad;
break;
case 'T':
fval = atan2(farg,fval);
break;
case 'p':
fval = pow(fval,farg);
break;
default: /* logical op */
if (nodetype(arg) == INT)
err_logo(BAD_DATA_UNREC, make_floatnode(fval));
else
err_logo(BAD_DATA_UNREC,arg);
}
} else { /* floating overflow de